"""
技术指标分析器
计算各种技术指标
"""
import numpy as np
import pandas as pd
from typing import List, Dict, Optional
import logging

logger = logging.getLogger(__name__)

class TechnicalAnalyzer:
    """技术分析器"""
    
    @staticmethod
    def calculate_ma(prices: List[float], period: int) -> Optional[float]:
        """计算移动平均线"""
        if len(prices) < period:
            return None
        return np.mean(prices[-period:])
    
    @staticmethod
    def calculate_ema(prices: List[float], period: int) -> Optional[float]:
        """计算指数移动平均线"""
        if len(prices) < period:
            return None
        df = pd.DataFrame({'price': prices})
        ema = df['price'].ewm(span=period, adjust=False).mean().iloc[-1]
        return float(ema)
    
    @staticmethod
    def calculate_macd(prices: List[float]) -> Dict[str, Optional[float]]:
        """
        计算 MACD 指标
        返回: {macd, signal, histogram}
        """
        if len(prices) < 26:
            return {"macd": None, "signal": None, "histogram": None}
        
        df = pd.DataFrame({'price': prices})
        
        # 计算 EMA
        ema12 = df['price'].ewm(span=12, adjust=False).mean()
        ema26 = df['price'].ewm(span=26, adjust=False).mean()
        
        # MACD 线
        macd_line = ema12 - ema26
        
        # 信号线
        signal_line = macd_line.ewm(span=9, adjust=False).mean()
        
        # MACD 柱
        histogram = macd_line - signal_line
        
        return {
            "macd": float(macd_line.iloc[-1]),
            "signal": float(signal_line.iloc[-1]),
            "histogram": float(histogram.iloc[-1])
        }
    
    @staticmethod
    def calculate_rsi(prices: List[float], period: int = 14) -> Optional[float]:
        """计算 RSI 指标"""
        if len(prices) < period + 1:
            return None
        
        df = pd.DataFrame({'price': prices})
        
        # 计算价格变化
        delta = df['price'].diff()
        
        # 分离上涨和下跌
        gain = delta.where(delta > 0, 0)
        loss = -delta.where(delta < 0, 0)
        
        # 计算平均涨跌
        avg_gain = gain.rolling(window=period).mean()
        avg_loss = loss.rolling(window=period).mean()
        
        # 计算 RS 和 RSI
        rs = avg_gain / avg_loss
        rsi = 100 - (100 / (1 + rs))
        
        return float(rsi.iloc[-1])
    
    @staticmethod
    def calculate_kdj(high: List[float], low: List[float], close: List[float], 
                     period: int = 9) -> Dict[str, Optional[float]]:
        """
        计算 KDJ 指标
        返回: {k, d, j}
        """
        if len(close) < period:
            return {"k": None, "d": None, "j": None}
        
        df = pd.DataFrame({
            'high': high,
            'low': low,
            'close': close
        })
        
        # 计算 RSV
        low_min = df['low'].rolling(window=period).min()
        high_max = df['high'].rolling(window=period).max()
        rsv = (df['close'] - low_min) / (high_max - low_min) * 100
        
        # 计算 K 和 D
        k = rsv.ewm(com=2, adjust=False).mean()
        d = k.ewm(com=2, adjust=False).mean()
        j = 3 * k - 2 * d
        
        return {
            "k": float(k.iloc[-1]) if not pd.isna(k.iloc[-1]) else None,
            "d": float(d.iloc[-1]) if not pd.isna(d.iloc[-1]) else None,
            "j": float(j.iloc[-1]) if not pd.isna(j.iloc[-1]) else None
        }
    
    @staticmethod
    def calculate_bollinger_bands(prices: List[float], period: int = 20, 
                                  std_dev: int = 2) -> Dict[str, Optional[float]]:
        """
        计算布林带
        返回: {upper, middle, lower}
        """
        if len(prices) < period:
            return {"upper": None, "middle": None, "lower": None}
        
        df = pd.DataFrame({'price': prices})
        
        # 中轨 (SMA)
        middle = df['price'].rolling(window=period).mean()
        
        # 标准差
        std = df['price'].rolling(window=period).std()
        
        # 上轨和下轨
        upper = middle + (std * std_dev)
        lower = middle - (std * std_dev)
        
        return {
            "upper": float(upper.iloc[-1]),
            "middle": float(middle.iloc[-1]),
            "lower": float(lower.iloc[-1])
        }
    
    def analyze_stock(self, price_data: List[Dict]) -> Dict:
        """
        综合技术分析
        """
        if not price_data:
            return {}
        
        # 提取价格数据
        closes = [p['close'] for p in price_data]
        highs = [p['high'] for p in price_data]
        lows = [p['low'] for p in price_data]
        
        # 计算各项指标
        indicators = {
            "ma5": self.calculate_ma(closes, 5),
            "ma10": self.calculate_ma(closes, 10),
            "ma20": self.calculate_ma(closes, 20),
            "ma60": self.calculate_ma(closes, 60) if len(closes) >= 60 else None,
            **self.calculate_macd(closes),
            "rsi": self.calculate_rsi(closes),
            **self.calculate_kdj(highs, lows, closes),
            **self.calculate_bollinger_bands(closes)
        }
        
        return indicators

